#ifndef smg_h
#define smg_h

// this header needs
#include "../file.h"

// header that defines some common variables/functions
// that can be used on different file formats

// padding string
// it is used to pad data up to a 4 or 32 byte multiple (serves for alignment)
owl_str OWL_SMG_PAD_STR = {
  &((owl_mem_space) {(void *) "This is padding data to alignme", 31}),
  OWL_WCHAR_ENC_SHIFT_JIS,
  OWL_INV_SHIFT_JIS,
  OWL_SHIFT_JIS_NULL,
  owl_check_wchar_shift_jis,
  owl_check_wchar_enc_shift_jis,
  owl_get_wchar_shift_jis,
  owl_write_wchar_enc_shift_jis,
  owl_print_wchar_shift_jis,
  owl_print_wchar_enc_shift_jis,
  owl_wchar_shift_jis_as_unicode,
  owl_wchar_unicode_as_shift_jis,
  OWL_SHIFT_JIS_NUM,
  OWL_SHIFT_JIS_WSP,
  OWL_SHIFT_JIS_PATH,
  OWL_SHIFT_JIS_LETR
};

// functions to get the size of a padding string given a byte position
owl_byte owl_get_padding_align_4_length(owl_umax byte_pos);
owl_byte owl_get_padding_align_32_length(owl_umax byte_pos);

// name tables

// constants
#define OWL_SMG_NAME_TABLE_UNKNOWN1 0xFFFF

// structure
// count - 16 bits
// unknown 1 - 16 bits (always 0xFFFF?)
// --- repeated count times
// hash - 16 bits
// index - 16 bits
// --- end
// --- repeated count times
// shift jis enc string (null terminated)
// --- end

// main information (most relevant information)
typedef struct {    // size in binary file
  owl_umax count;   // 16bits
  owl_str ** names; // depends on the length of each name (null terminated all, shift_jis encoded)
} owl_smg_name_table_main;

// extra information (can be determined from main information)
typedef struct {      // size in binary file
  owl_umax unknown1;  // 16bits (seems to be always 0xFFFF)
  struct owl_smg_name_table_name_data { 
    owl_umax hash;    // 16bits
    owl_umax index;   // 16bits
  } * names_data;     // (2 * 16bits) * str_count
} owl_smg_name_table_extra;

// the actual structure
typedef struct {
  owl_smg_name_table_main * main;
  owl_smg_name_table_extra * ext;
} owl_smg_name_table;

// enum with the possible codes a name table will present while analizing it
// all errors are named to indicate the place of the read error (in the best case)
// other errors are related to logic errors when reading the raw string
typedef enum {
  OWL_SMG_NAME_TABLE_ERR_ALL_GOOD,
  
  OWL_SMG_NAME_TABLE_ERR_FUNC_PARAMS,
  OWL_SMG_NAME_TABLE_ERR_STR_SIZE,
  OWL_SMG_NAME_TABLE_ERR_MEM_ALLOC,
  
  OWL_SMG_NAME_TABLE_ERR_COUNT,
  OWL_SMG_NAME_TABLE_ERR_UNKNOWN1,
  OWL_SMG_NAME_TABLE_ERR_NAME_HASH_INDEX,
  OWL_SMG_NAME_TABLE_ERR_NAME,
  
  OWL_SMG_NAME_TABLE_ERR_LIMIT,
} owl_smg_name_table_err_cd;

// global variable for the owl_create_smg_name_table()
// function used by the owl_get_err_cd_smg_name_table()
owl_smg_name_table_err_cd OWL_SMG_NAME_TABLE_ERR_CD = OWL_SMG_NAME_TABLE_ERR_ALL_GOOD;
owl_umax OWL_SMG_NAME_TABLE_ERR_READ_POS = 0;

// basic functions
owl_bool owl_check_smg_name_table_main_pointer(owl_byte * src, owl_umax size);
owl_bool owl_check_smg_name_table_ext_pointer(owl_byte * src, owl_umax size);
owl_bool owl_check_smg_name_table_pointer(owl_byte * src, owl_umax size);
owl_bool owl_check_smg_name_table_main_members(owl_umax count, owl_str ** names);
owl_bool owl_check_smg_name_table_main_all(owl_smg_name_table_main * main, owl_umax size);
owl_bool owl_check_smg_name_table_all(owl_smg_name_table * names, owl_umax size);
owl_smg_name_table * owl_create_smg_name_table(owl_str * raw, owl_endian endian);
owl_umax owl_free_smg_name_table(owl_smg_name_table * names);
owl_umax owl_print_smg_name_table(owl_byte * src, owl_umax size);
owl_char owl_comp_smg_name_table(owl_byte * names1, owl_byte * names2);

// specific functions
owl_bool owl_get_smg_name_table_extra(owl_smg_name_table * names);
owl_umax owl_get_smg_name_table_bin_size(owl_smg_name_table * names);
owl_smg_name_table_err_cd owl_get_err_cd_smg_name_table(owl_str * raw, owl_endian endian);
owl_smg_name_table * owl_get_smg_name_table_min_args(owl_umax count, owl_str ** names);
owl_str * owl_get_smg_name_table_as_str(owl_smg_name_table * names, owl_endian endian);

#include "smg.c"

#endif // smg_h
